package sortowania;
/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author student
 */
public class Sortowania {

    private static long time;
    static int[] t;
    static String path = "C:\\Users\\AXELA\\Documents\\NetBeansProjects\\Sortowania\\tablica.txt";

    /**
     * @param args the command line arguments
     */
    public static int[] wczytajZPalca() {//metoda wczytująca
        int n = Integer.parseInt(JOptionPane.showInputDialog(null, "Podaj liczbę elementów tablicy do posortowania"));
        int[] tablica = new int[n];
        int i = 0;
        for (; i < n; i++) {
            int liczba = Integer.parseInt(JOptionPane.showInputDialog(null, "Podaj kolejną liczbę"));
            tablica[i] = liczba;
        }
        return tablica;
    }//koniec metody wczytującej

    public static void wyswietl(int tablica[]) {//metoda wyswietlająca
        System.out.println(Arrays.toString(tablica));
    }//koniec metody wyświetlającej

    public static int[] wczytajZPliku(String filePath) {
        FileReader plik = null;
        int[] tablica=null;
        try {
            plik = new FileReader(filePath);
            BufferedReader plikZbuforowany = new BufferedReader(plik);
            String liniaDanych = "";
            try {
                liniaDanych = plikZbuforowany.readLine();
            } catch (IOException ex) {
                ex.printStackTrace();
                Logger.getLogger(Sortowania.class.getName()).log(Level.SEVERE, null, ex);
            }
            int licznik = 0;
            String[] tablicaNapisow = liniaDanych.split("\\s");
            tablica = new int[tablicaNapisow.length];
            for (int i = 0; i < tablica.length; i++) {
                tablica[i] = Integer.parseInt(tablicaNapisow[i]);
            }
        } //koniec metody wczytujacej z plikui
        catch (FileNotFoundException ex) {
            ex.printStackTrace();
            Logger.getLogger(Sortowania.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                plik.close();
            } catch (IOException ex) {
                ex.printStackTrace();
                Logger.getLogger(Sortowania.class.getName()).log(Level.SEVERE, null, ex);
            }
            return tablica;
        }
    }//koniec metody wczytujacej z plikui

    public static void wyswietlZPliku(String filePath) {
        FileReader plik = null;
        try {
            plik = new FileReader(filePath);
            BufferedReader plikZbuforowany = new BufferedReader(plik);
            String liniaDanych = "";
            liniaDanych = plikZbuforowany.readLine();
            String[] tabilcaNapisow = liniaDanych.split("\\s");
            for (int i = 0; i < tabilcaNapisow.length; i++) {
                System.out.println(tabilcaNapisow[i]);
            }
        } //koniec metody wyswietlajacej z pliku
        catch (IOException ex) {
            ex.printStackTrace();
            Logger.getLogger(Sortowania.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                plik.close();
            } catch (IOException ex) {
                ex.printStackTrace();
                Logger.getLogger(Sortowania.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }//koniec metody wyswietlajacej z pliku

    public static int[] wczytajLosoweLiczby(int n, int zakres) {//wczytywanie losowych liczb do tablicy
        int[] tablica = new int[n];
        Random r = new Random();
        int i = 0;
        for (; i < n; i++) {
            int liczba = r.nextInt(zakres);
            tablica[i] = liczba;
        }
        return tablica;
    }//koniec metody wczytujacej losowe liczny do tablicy

    public static boolean zapiszDoPliku(int[] t, String path) {
        FileWriter fr = null;
        try {
            fr = new FileWriter(path);
            for (int i = 0; i < t.length; i++) {
                int j = t[i];
                fr.write(j + " ");
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            Logger.getLogger(Sortowania.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                fr.close();
            } catch (IOException ex) {
                ex.printStackTrace();
                Logger.getLogger(Sortowania.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return true;
    }

    public static void main(String[] args) throws FileNotFoundException, IOException {
        normalneDzialanie();
//        testowanie();
    }

    public static void normalneDzialanie() {
        wyswietlCzasyKontaktZPlikiem();
    }

    public static void quickSort(int p, int k) {
        long tim = System.currentTimeMillis();
        if (p < k) {
            int x = t[t.length - 1];
            int s = divide(t[k], p, k);
            quickSort(p, s - 1);
            quickSort(s + 1, k);
        }
        Sortowania.time = System.currentTimeMillis() - tim;
    }

    public static int divide(int x, int p, int q) {
        int i = p - 1;
        int temp;
        for (int j = p; j < q; j++) {
            if (t[j] <= x && i < q) {
                i++;
                temp = t[i];
                t[i] = t[j];
                t[j] = temp;
            }
        }
        temp = t[i + 1];
        t[i + 1] = t[q];
        t[q] = temp;

        return i + 1;

    }

    public static void testowanie() {
        //TEST
        boolean czyAlgorytmDzialaPoprawnie = true;///Ta wartosc testuje dzialanie algorytmu
///            czyAlgorytmDzialaPoprawnie=czyAlgorytmDzialaPoprawnie && false;
        for (int i = 0; i < 100; i++) {
            t = wczytajLosoweLiczby(150, 200);
            sortowanieBabelkowe();
            czyAlgorytmDzialaPoprawnie = czyAlgorytmDzialaPoprawnie && sprCzyPosortowana(t);
        }
        System.out.println(czyAlgorytmDzialaPoprawnie + " //wartosc true oznacza, ze powyzsza tablica jest posortowana");
    }

    public static boolean sprCzyPosortowana(int[] t) {
        boolean ok = true;
        for (int i = 0; i < t.length - 1 && ok; i++) {
            if (t[i] > t[i + 1]) {
                ok = false;
            }
        }
        return ok;
    }
@Deprecated
    public static void wyswietlCzasyNiepoprawnie() {
        /**
         * za kazdym razem wczytuja sie inne dane, takze ten sposob jest
         * niepoprawny inaczej: dla roznych danych
         */
        wyswietlCzasSortowaniaNiepoprawnie(1000);
        wyswietlCzasSortowaniaNiepoprawnie(10000);
        wyswietlCzasSortowaniaNiepoprawnie(100000);
    }

    public static void wyswietlCzasyKontaktZPlikiem() {
        System.out.println("Przy analizie czasow nalezy pamietac, ze program zapisuje i odczytuje dane z pliku");
        System.out.println("(Rozmiar tablicy jest za duzy, aby tego uniknac - wystepuje wowczas blad StackOverflow)\n");
        String naglowek;//=String.format("%25s || %25s || %25s", "Rozmiar danych", "Czas sortowania babelkowego", "Czas sortowania quicksort");
        naglowek=String.format("Rozmiar danych || %30s || %30s ||", "czas sortowania babelkowego", "czas sortowania quicksort");
        System.out.println(naglowek);
        wyswietlCzasSortowaniaKontaktZPlikiem(1000);
        wyswietlCzasSortowaniaKontaktZPlikiem(10000);
        wyswietlCzasSortowaniaKontaktZPlikiem(100000);
        wyswietlCzasSortowaniaKontaktZPlikiem(1000000);
    }

    public static void wyswietlCzasSortowaniaNiepoprawnie(int n) {
        t = wczytajLosoweLiczby(n, 100);
        Sortowania.sortowanieBabelkowe();
        long timB = Sortowania.time;
        t = wczytajLosoweLiczby(n, 100);
        quickSort(0, t.length - 1);
        long timQ = Sortowania.time;
        String s = String.format("Rozmiar danych: %15s Czas sortowania bąbelkowego: %15s Czas sortowania quicksort: %15s", n, timB, timQ);
        System.out.println(s);
        System.gc();
    }

    public static void wyswietlCzasSortowaniaKontaktZPlikiem(int n) {
        t = wczytajLosoweLiczby(n, 100);
        zapiszDoPliku(t, path);
        Sortowania.sortowanieBabelkowe();
        long timB = Sortowania.time;
        t = wczytajZPliku(path);
        quickSort(0, t.length - 1);
        long timQ = Sortowania.time;
        String s = String.format("%15s||%32s||%32s||", n, timB, timQ);
        System.out.println(s);
        System.gc();
    }

    public static void wyswietlCzasSortowaniaQuicksort(int n) {
        t = wczytajLosoweLiczby(n, 100);
        Sortowania.quickSort(0, t.length - 1);
        long tim = Sortowania.time;
        String s = String.format("Rozmiar danych: %15s Czas sortowania: %15s", n, tim);
        System.out.println(s);
    }

    public static void sortowanieBabelkowe() {
        int n = t.length;
        int k = 1;
        long tim = System.currentTimeMillis();

        boolean zmiana = true;
        while (k < n && zmiana) {
            zmiana = false;
            for (int j = 0; j < n - k; j++) {
                if (t[j] > t[j + 1]) {
                    int temp = t[j];
                    t[j] = t[j + 1];
                    t[j + 1] = temp;
                    zmiana = true;
                }
            }
            k++;
        }
        Sortowania.time = System.currentTimeMillis() - tim;
    }
}